package com.supermap.wzhy.data;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.*;
import org.dom4j.io.SAXReader;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/* 需要Dom4j支持 */

/**
 * xml文档解析
 * Created by W.Qiong on 15-7-14.
 */

public class XMLHelper {

    private static Log logger= LogFactory.getLog(XMLHelper.class);

    /**
     *
     * <p>
     * 按照CLASSPATH路径解析XML
     * </p>
     *
     * @param strResource
     *            classpath路径
     * @return 文档对象
     */
    public static Document parseXml(String strResource) {
        Document doc = null;
        try {
            InputStream is = ConfigHelper.getResourceAsStream(strResource);
            doc = SAXReader.class.newInstance().read(is);
        } catch (DocumentException e) {
            e.printStackTrace();
            return null;
        } catch (InstantiationException e) {
            e.printStackTrace();
            return null;
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            return null;
        } catch (Exception e){
            e.printStackTrace();
            return null;
        }
        return doc;
    }

    /**
     *
     * <p>
     * 按照物理路径解析XML
     * </p>
     *
     * @param path
     *            物理路径
     * @return 文档对象
     */
    public static Document parseXmlPath(String path) {
        Document doc = null;
        try {
            doc = SAXReader.class.newInstance().read(new File(path));
        } catch (DocumentException e) {
            e.printStackTrace();
            return null;
        } catch (InstantiationException e) {
            e.printStackTrace();
            return null;
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            return null;
        }
        return doc;
    }

    /**
     *
     * <p>
     * 按照物理路径解析XML
     * </p>
     * @param path
     *            物理路径
     * @param encoding
     *            编码格式
     * @return 文档对象
     */
    public static Document parseXmlPath(String path, String encoding) {
        Document doc = null;
        try {
            SAXReader rd = SAXReader.class.newInstance();
            rd.setEncoding(encoding);
            FileReader fr = new FileReader(path);
            while (!fr.ready()) {
            }
            doc = rd.read(fr);
            fr.close();
        } catch (DocumentException e) {
            e.printStackTrace();
            return null;
        } catch (InstantiationException e) {
            e.printStackTrace();
            return null;
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            return null;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return doc;
    }

    /**
     *
     * <p>
     * 创建XML文档
     * </p>
     *
     * @param strPath
     *            文件生成的物理路径
     * @param strContent
     *            XML内容
     * @return 是否创建成功
     */
    public static boolean writeXml(String strPath, String strContent) {
        boolean blnFlag = false;
        try {
            File file = new File(strPath);
            FileWriter fw = new FileWriter(file);
            fw.write(strContent);
            fw.close();
            return true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return blnFlag;
    }

    /**
     *
     * <p>
     * 解析XML字符串
     * </p>
     * @param strXml
     *            xml字符串
     * @return 文档对象
     */
    public static Document parseXmlStr(String strXml) {
        Document doc = null;
        try {
            doc = DocumentHelper.parseText(strXml);
        } catch (DocumentException e) {
            e.printStackTrace();
            return null;
        }
        return doc;
    }

    /**
     *
     * <p>
     * 获取Element对象
     * </p>
     * @param doc
     *            文档对象
     * @param strXPath
     *            XPath路径
     * @return
     */
    public static Element getSingleElement(Document doc, String strXPath) {
        return (Element) doc.selectSingleNode(strXPath);
    }

    /**
     *
     * <p>
     * 获取Element对象集
     * </p>
     * @param doc
     *            文档对象
     * @param strXPath
     *            XPath路径
     * @return
     */
    @SuppressWarnings("unchecked")
    public static List<Element> getElements(Document doc, String strXPath) {
        return (List<Element>) doc.selectNodes(strXPath);
    }

    /**
     *
     * <p>
     * 获取Element对象集
     * </p>
     * @param element
     *            元素对象
     * @param strXpath
     *            XPath路径
     * @return 元素对象集合
     */
    @SuppressWarnings("unchecked")
    public static List<Element> getElements(Element element, String strXpath) {
        return (List<Element>) element.selectNodes(strXpath);
    }

    /**
     *
     * <p>
     * 获取当前元素的下一级元素
     * </p>
     * @param element
     *            元素对象
     * @return 元素对象集合
     */
    @SuppressWarnings("unchecked")
    public static List<Element> getChildrens(Element element) {
        return (List<Element>) element.elements();
    }

    /**
     *
     * <p>
     * 获取Element对象的属性
     * </p>
     * @param element
     *            元素对象
     * @param strAttribute
     *            属性名称
     * @return 属性值
     */
    public static String getAttribute(Element element, String strAttribute) {
        return element.attributeValue(strAttribute);
    }

    /**
     *
     * <p>
     * 获取Element对象的属性
     * </p>
     *
     * @param doc
     *            文档对象
     * @param strXPath
     *            XPath路径
     * @param strAttribute
     *            属性名称
     * @return 属性值
     */
    public static String getAttribute(Document doc, String strXPath,
                                      String strAttribute) {
        return ((Element) doc.selectSingleNode(strXPath))
                .attributeValue(strAttribute);
    }

    /**
     *
     * <p>
     * 获取元素对象的节点值
     * </p>
     *
     * @param element
     *            元素对象
     * @return 节点值
     */
    public static String getText(Element element) {
        return element.getTextTrim();
    }

    /**
     *
     * <p>
     * 获取元素对象的节点值
     * </p>
     * @param doc
     *            文档对象
     * @param strXPath
     *            XPath
     * @return
     */
    public static String getText(Document doc, String strXPath) {
        return ((Element) doc.selectSingleNode(strXPath)).getTextTrim();
    }

    /**
     *
     * <p>
     * 根据属性值查询元素对象
     * </p>
     * @param doc
     *            文档对象
     * @param strXPath
     *            XPath路径
     * @param attrName
     *            属性名称
     * @param attrValue
     *            属性值
     * @return 元素对象集合
     */
    public static List<Element> getElementsByAttrValue(Document doc,
                                                       String strXPath, String attrName, String attrValue) {
        List<Element> list = getElements(doc, strXPath);
        List<Element> returnList = new ArrayList<Element>();
        for (Element element : list) {
            if (getAttribute(element, attrName).equals(attrValue)) {
                returnList.add(element);
            }
        }
        return returnList;
    }

    /**
     *
     * <p>
     * 删除指定路径下指定位置的节点
     * </p>
     * @param doc
     * @param strPath
     * @param seq
     * @return
     */
    public static Document deleteElementBySeq(Document doc, String strPath,
                                              int seq) {
        List list = doc.selectNodes(strPath);
        Element element = (Element) list.get(seq);
        boolean b = element.getParent().remove(element);
        return doc;
    }

    /**
     *
     * <p>
     * 指定节点增加一个子节点
     * </p>
     * @param doc
     * @param strPath
     * @param element
     * @return
     */
    public static Document addElement(Document doc, String strPath,
                                      Element element) {
        Element parentElement = (Element) doc.selectSingleNode(strPath);
        parentElement.add(element);

        return doc;
    }

    /**
     *
     * <p>
     * 更新指定节点的属性
     * </p>
     * @param doc
     * @param strPath
     * @param strName
     * @param strValue
     * @return
     */
    public static Document updateElement(Document doc, String strPath,
                                         String strName, String strValue) {
        Element parentElement = (Element) doc.selectSingleNode(strPath);
        Attribute attribute = parentElement.attribute(strName);
        attribute.setValue(strValue);
        return doc;
    }

}

